#pragma once

#include "Thread_mutex.hpp"
#include <queue>

using namespace std;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t productor = PTHREAD_COND_INITIALIZER;
pthread_cond_t consumer = PTHREAD_COND_INITIALIZER;

template<class T>
class BlockQueue
{
public:

    BlockQueue(){}

    BlockQueue(int data)
        :_data(data)
    {}

    bool IsFull()
    {
        return que.size() == _data;            
    }

    bool IsNull()
    {
        return que.empty();
    }

    void Push(T& in)
    {
        pthread_mutex_lock(&mutex);
        if(IsFull())
        {
            pthread_cond_wait(&productor, &mutex);
        }
      
        cout << "--funcofmain" << ">>生产in: " << in << endl;
        que.push(in);
        pthread_cond_signal(&consumer);

        pthread_mutex_unlock(&mutex);
    }

    void Pop(T& out)
    {
        pthread_mutex_lock(&mutex);
        if(IsNull())
        {
            pthread_cond_wait(&consumer, &mutex);
        }

        cout << "--funcofless" <<  ">>消费out: " << out << endl;
        out = que.front();
        que.pop();
        pthread_cond_signal(&productor);     

        pthread_mutex_unlock(&mutex);  
    }

private:
    int _data;
    queue<T> que;
};